<?php
/* 
 *	文件上传类
 *  author chendan at 2011.09.01.
*/
class Upload {
	protected $_uploaded = array();
	protected $_destination;
	protected $_max = 51200;
	protected $_messages = array();
	protected $_permitted = array('image/gif','image/png','image/jpg','image/jpeg','image/pjpeg','image/x-png');
	protected $_renamed = false;
	protected $_filename = array();

	public function __construct($path) {
		if(!is_dir($path)||!is_writable($path)){
			throw new Exception("$path must be a valid,writable directory.");
		}
		$this->_destination = $path;
		$this->_uploaded = $_FILES;
	}
	//移动文件
	public function move($overwrite = false) {
		$field = current($this->_uploaded);
		if(is_array($field['name'])){
			foreach($field['name'] as $number => $filename){
				$this->_renamed = false;
				$this->processFile($filename,$field['error'][$number],$field['size'][$number],$field['type'][$number],$field['tmp_name'][$number],$overwrite);
			}
		}else{
			$this->processFile($field['name'],$field['error'],$field['size'],$field['type'],$field['tmp_name'],$overwrite);
		}
	}

	public function getMessages() {
		return $this->_messages;
	}

	protected function checkError($filename,$error) {
		switch($error){
			case 0:
				return true;
			case 1:
			case 2:
				$this->_messages[] = "$filename exceeds maxinum size: ".$this->getMaxSize();
				return false;
			case 3:
				$this->_messages[] = "Error uploading $filename,please try again.";
				return false;
			case 4:
				$this->_messages[] = "没有选择上传的文件!";
				return false;
			default:
				$this->_messages[] = "System error uploading $filename,Contact webmaster.";
				return false;
		}
	}

	protected function checkSize($filename,$size) {
		if($size == 0){
			return false;
		}elseif($size>$this->_max){
			$this->_messages[] = "$filename 大小限制在".$this->getMaxSize();
			return false;
		}else{
			return true;
		}
	}

	protected function checkType($filename,$type) {
		if(empty($type)){
			return false;
		}elseif(!in_array($type,$this->_permitted)){
			$this->_messages[] = "$filename 是不允许上传的类型!上传失败!";
			return false;
		}else{
			return true;
		}
	}

	public function getMaxSize() {
		return number_format($this->_max/1024,1).'kb';
	}

	public function addPermittedTypes($types) {
		$types = (array)$types;
		$this->isValidMime($types);
		$this->_permitted = array_merge($this->_permitted,$types);
	}

	public function setPermittedTypes($types) {
		$types = (array) $types;
		$this->isValidMime($types);
		$this->_permitted = $types;
	}

	protected function isValidMime($types) {
		$alsoValid = array('image/tiff','application/pdf','text/plain','text/rtf');
		$valid = array_merge($this->_permitted,$alsoValid);
		foreach($types as $type){
			if(!in_array($type,$valid)){
				throw new Exception("$type is not a permitted MIME type");
			}
		}
	}

	public function setMaxSize($num) {
		if(!is_numeric($num)){
			throw new Exception("Maximum size must be a number.");
		}
		$this->_max = (int)$num;
	}

	//检测名称是否重复
	protected function checkName($name,$overwrite) {
		$nospace = str_replace(' ','_',$name);
		if($nospace != $name){
			$this->_rename = true;
		}
		if(!$overwrite){
			//rename the file if it already exists
			$existing = scandir($this->_destination);
			if(in_array($nospace,$existing)){
				$dot = strrpos($nospace,'.');
				if($dot){
					$base = substr($nospace,0,$dot);
					$extension = substr($nospace,$dot);
				}else{
					$base = $nospace;
					$extension = '';
				}
				$i = 1;
				do{
					$nospace = $base.'_'.$i++.$extension;
				}while(in_array($nospace,$existing));
				$this->_renamed = true;
			}
		}
		$this->_filename[] = $nospace;
		return $nospace;
	}

	//处理上传(包括文件类型，大小检查，名称检查)
	protected function processFile($filename,$error,$size,$type,$tmp_name,$overwrite) {
		$ok = $this->checkError($filename,$error);
		if($ok){
			$type_ok = $this->checkType($filename,$type);
			$size_ok = $this->checkSize($filename,$size);
			if($type_ok && $size_ok){
				$name = $this->checkName($filename,$overwrite);
				$success = move_uploaded_file($tmp_name,$this->_destination.$name);
				if($success){
					$message = $filename." 上传成功!";
					if($this->_renamed){
						$message .= " 并且重命名为 $name!";
					}
					$this->_messages[] = $message;
					return true;
				}else{
					$this->_messages[] = "不能上传文件 ".$filename;
					return false;
				}
			}
		}
		return false;
	}
	public function getFilename() {
		return $this->_filename;
	}
}
?>